package com.weijianhuawen.wjblog.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.weijianhuawen.wjblog.admin.convert.UserConvert;
import com.weijianhuawen.wjblog.admin.event.UpdatePersonMessageEvent;
import com.weijianhuawen.wjblog.admin.mode.vo.user.*;
import com.weijianhuawen.wjblog.admin.service.AdminUserService;
import com.weijianhuawen.wjblog.common.domain.dos.UserDetailDo;
import com.weijianhuawen.wjblog.common.domain.dos.UserDo;
import com.weijianhuawen.wjblog.common.domain.dos.UserRoleDo;
import com.weijianhuawen.wjblog.common.domain.mapper.UserDetailMapper;
import com.weijianhuawen.wjblog.common.domain.mapper.UserMapper;
import com.weijianhuawen.wjblog.common.domain.mapper.UserRoleMapper;
import com.weijianhuawen.wjblog.common.domain.qo.UserDetailQo;
import com.weijianhuawen.wjblog.common.enums.ResponseCodeEnum;
import com.weijianhuawen.wjblog.common.enums.UserAccountStatusEnum;
import com.weijianhuawen.wjblog.common.exception.BizException;
import com.weijianhuawen.wjblog.common.utils.DateUtil;
import com.weijianhuawen.wjblog.common.utils.PageResponse;
import com.weijianhuawen.wjblog.common.utils.Response;
import com.weijianhuawen.wjblog.common.utils.ValidateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @version: java version 8
 * @Author: weijianhuawen
 * @description:
 * @date: 2024-10-19 12:56
 */
@Service
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserDetailMapper userDetailMapper;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Value("${image.default.url}")
    private String defaultImageUrl;

    /**
     * 修改密码
     * @param vo 请求体数据
     * @return 响应结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response<Object> updateAdminUserPassword(UpdateAdminUserPasswordReqVo vo) {
        //获取用户名与密码
        String username = vo.getUsername();
        String password = vo.getPassword();
        // 获取当前登录用户名
        String currentLoginUsername = getUserUsername();
        if (!Objects.equals(username, currentLoginUsername)) throw new BizException(ResponseCodeEnum.USER_NOT_CONSISTENT);
        //获旧密码
        String oldPassword = vo.getOldPassword();
        //从数据库获取用户，并验证旧密码
        UserDo userDo = userMapper.findByUsername(username);
        if (Objects.isNull(userDo)) {
            //用户不存在
            return Response.fail(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        //验证旧密码
        if (!passwordEncoder.matches(oldPassword, userDo.getPassword())) {
            //旧密码验证失败，修改失败
            return Response.fail(ResponseCodeEnum.OLD_PASSWORD_ERROR);
        }
        //新密码加密
        String encodePassword = passwordEncoder.encode(password);
        //更新到数据库
        int count = userMapper.updatePasswordByUsername(username, encodePassword);

        return count == 1 ? Response.success() : Response.fail(ResponseCodeEnum.USERNAME_NOT_FOUND);
    }

    /**
     * 获取当前用户的用户名
     * @return 用户名
     */
    @Override
    public Response<Object> findUserInfo() {
        //获取储存在ThreadLocal中的用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取用户名
        String username = authentication.getName();
        return Response.success(FindUserInfoRspVo.builder().username(username).build());
    }

    @Override
    public Response findUserDetailInformation() {
        // 获取储存在ThreadLocal中的用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 获取用户名
        String username = authentication.getName();

        // 查找账户
        UserDo userDo = userMapper.findByUsername(username);
        if (Objects.isNull(userDo)) {
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        // 获取用户id
        Long userId = userDo.getId();

        // 查询用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(userDetailDo)) {
            // 用户信息为空，创建临时用户信息
            autoGenerateUserDetail(userId, username);
            userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        }
        // do转vo
        log.info(userDetailDo.toString());
        FindUserDetailInformationRspVo vo = UserConvert.INSTANCE.Do2findVo(userDetailDo);
        // 处理手机号
        String phone = formatPhoneNumber(userDetailDo.getPhoneNumber());
        vo.setPhoneNumber(phone);
        vo.setUsername(username);
        return Response.success(vo);
    }

    @Override
    public Response findUserBaseInfo() {
        // 获取用户名
        String username = getUserUsername();

        // 查找账户
        UserDo userDo = userMapper.findByUsername(username);
        if (Objects.isNull(userDo)) {
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        // 获取用户id
        Long userId = userDo.getId();

        // 查询用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(userDetailDo)) {
            // 用户信息为空，创建临时用户信息
            autoGenerateUserDetail(userId, username);
            userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        }
        FindUserBaseInformationRspVo rspVo = FindUserBaseInformationRspVo.builder()
                .userId(String.valueOf(userId))
                .username(username)
                .avatar(userDetailDo.getAvatar())
                .nickname(userDetailDo.getNickname())
                .mail(userDetailDo.getMail())
                .isAdmin(userDetailDo.getIsAdmin())
                .build();

        return Response.success(rspVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response updateUserDetailInformation(UpdateUserDetailInformationReqVo vo) {
        // 获取用户id
        Long userId = vo.getUserId();

        // 查询账户是否存在
        UserDo userDo = userMapper.selectById(userId);
        if (Objects.isNull(userDo)) {
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }

        // 查询用户详细信息是否存在
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.nonNull(userDetailDo)) {
            // 用户详细信息存在，则更新信息
            UserDetailDo updateDo = UserConvert.INSTANCE.updateVo2Do(vo);
            // 设置id
            updateDo.setId(userDetailDo.getId());
            // 设置更新时间
            updateDo.setUpdateTime(LocalDateTime.now());
            // 更新数据
            userDetailMapper.updateById(updateDo);
        } else {
            // 用户详细信息不存在则创建
            UserDetailDo updateDo = UserConvert.INSTANCE.updateVo2Do(vo);
            // 保存数据
            userDetailMapper.insert(updateDo);
        }
        // 发布修改个人资料事件
        eventPublisher.publishEvent(new UpdatePersonMessageEvent(this, userId));
        return Response.success();
    }

    @Override
    public Response updateUserPersonInformation(UpdateUserPersonInformationReqVo vo) {
        // 获取用户id
        Long userId = vo.getUserId();
        // 判断用户是否存在
        if (!isExistUserCount(userId)) throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);

        // 查询用户详细信息是否存在
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.nonNull(userDetailDo)) {
            // 用户详细信息存在，则更新信息
            userDetailDo.setAvatar(vo.getAvatar());
            userDetailDo.setNickname(vo.getNickname());
            userDetailDo.setSignature(vo.getSignature());
            userDetailDo.setLocalCity(vo.getLocalCity());
            userDetailDo.setUniversity(vo.getUniversity());
            userDetailDo.setSex(vo.getSex());
            userDetailDo.setBirthday(vo.getBirthday());
            userDetailDo.setGitee(vo.getGitee());
            userDetailDo.setGithub(vo.getGithub());
            userDetailDo.setIntroduce(vo.getIntroduce());
            userDetailDo.setPersonBlog(vo.getPersonBlog());
            // 设置更新时间
            userDetailDo.setUpdateTime(LocalDateTime.now());
            // 更新数据
            userDetailMapper.updateById(userDetailDo);
        } else {
            // 用户信息不存在，则无法修改
            throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);
        }
        // 发布修改个人资料事件
        eventPublisher.publishEvent(new UpdatePersonMessageEvent(this, userId));
        return Response.success();
    }

    @Override
    public Response findUserCountInfo() {
        String username = getUserUsername();
        // 获取userid
        UserDo userDo = userMapper.findByUsername(username);
        if (Objects.isNull(userDo)) throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        Long userId = userDo.getId();

        // 查询用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(userDetailDo)) throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);

        // 获取邮箱
        String mail = userDetailDo.getMail();
        // 获取手机号
        String phoneNumber = userDetailDo.getPhoneNumber();
        // 获取qq
        String qqId = userDetailDo.getQqId();

        // 创建请求vo
        FindCountInfoRspVo vo = FindCountInfoRspVo.builder()
                .userId(String.valueOf(userId))
                .username(username)
                .phoneNumber(formatPhoneNumber(phoneNumber))
                .qqId(qqId)
                .mail(mail)
                .build();

        // 返回响应
        return Response.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response updateCountPhone(UpdateCountPhoneReqVo vo) {
        // 获取用户id与用户名
        Long userId = vo.getUserId();
        String username = vo.getUsername();
        // 获取并验证用户账号
        UserDo userDo = validateUserCount(userId, username, vo.getPassword());
        // 获取旧手机号
        String phoneNumber = vo.getPhoneNumber();
        // 获取新手机号
        String newPhoneNumber = vo.getNewPhoneNumber();
        // 验证手机号码是否为纯数字
        if (!isPureNumber(newPhoneNumber) || (StringUtils.isNotBlank(phoneNumber) && !isPureNumber(phoneNumber))) throw new BizException(ResponseCodeEnum.PHONE_NUMBER_FORMAT_ERROR);
        // 验证新手机号是否绑定其他账号
        if (isBindAccount(newPhoneNumber, null, null)) throw new BizException(ResponseCodeEnum.USER_MAIL_OR_PHONE_OR_QQ_ALREADY_REGISTER);
        // 获取用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userDo.getId());
        if (Objects.isNull(userDetailDo)) throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);
        // 验证旧手机号是否正确
        if (StringUtils.isNotBlank(userDetailDo.getPhoneNumber()) && !Objects.equals(userDetailDo.getPhoneNumber(), phoneNumber)){
            throw new BizException(ResponseCodeEnum.PHONE_NUMBER_VALIDATE_ERROR);
        }

        // 更新手机号
        userDetailDo.setPhoneNumber(newPhoneNumber);
        // 保存
        userDetailMapper.updateById(userDetailDo);
        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response updateCountMail(UpdateCountMailReqVo vo) {
        // 获取用户id与用户名
        Long userId = vo.getUserId();
        String username = vo.getUsername();
        // 获取并验证用户账号
        UserDo userDo = validateUserCount(userId, username, vo.getPassword());

        // 获取新邮箱
        String mail = vo.getMail();
        // 验证新邮箱是否被其他账号绑定
        if (isBindAccount(null, mail, null)) throw new BizException(ResponseCodeEnum.USER_MAIL_OR_PHONE_OR_QQ_ALREADY_REGISTER);

        // 获取用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userDo.getId());
        if (Objects.isNull(userDetailDo)) throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);

        // 更新邮箱
        userDetailDo.setMail(mail);
        // 保存
        userDetailMapper.updateById(userDetailDo);
        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response updateCountQq(UpdateCountQqReqVo vo) {
        // 获取用户id与用户名
        Long userId = vo.getUserId();
        String username = vo.getUsername();
        // 获取并验证用户账号
        UserDo userDo = validateUserCount(userId, username, vo.getPassword());

        // 获取新qq号
        String qqId = vo.getQqId();
        // 验证qq号码是否为纯数字
        if (!isPureNumber(qqId)) throw new BizException(ResponseCodeEnum.QQID_FORMAT_ERROR);
        // 验证新qq号是否绑定其他账号
        if (isBindAccount(null, null, qqId)) throw new BizException(ResponseCodeEnum.USER_MAIL_OR_PHONE_OR_QQ_ALREADY_REGISTER);
        // 获取用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userDo.getId());
        if (Objects.isNull(userDetailDo)) throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);

        // 更新qq号码
        userDetailDo.setQqId(qqId);
        // 保存
        userDetailMapper.updateById(userDetailDo);
        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response unbindUserQq(UnbindUserCountQqReqVo vo) {
        // 获取用户名与用户id
        Long userId = vo.getUserId();
        String username = vo.getUsername();
        String password = vo.getPassword();
        // 验证用户
        UserDo userDo = validateUserCount(userId, username, password);

        // 获取用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userDo.getId());

        if (Objects.isNull(userDetailDo)) throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);

        // 查询用户是否绑定qq
        if (Objects.isNull(userDetailDo.getQqId())) throw new BizException(ResponseCodeEnum.USER_UNBIND_QQID);

        // 用户绑定qq，将qq号置空，更新信息
        userDetailDo.setQqId(null);
        LambdaUpdateWrapper<UserDetailDo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(UserDetailDo::getQqId, null);
        updateWrapper.eq(UserDetailDo::getId, userDetailDo.getId());
        userDetailMapper.update(userDetailDo, updateWrapper);
        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response unbindUserPhone(UnbindUserCountPhoneReqVo vo) {
        // 获取用户名，用户id，密码
        Long userId = vo.getUserId();
        String username = vo.getUsername();
        String password = vo.getPassword();
        // 获取账号对象，并验证
        UserDo userDo = validateUserCount(userId, username, password);

        // 获取手机号
        String phone = vo.getPhoneNumber();
        // 验证手机号格式
        if (!isPureNumber(phone)) throw new BizException(ResponseCodeEnum.PHONE_NUMBER_FORMAT_ERROR);
        // 查询用户详细信息
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userDo.getId());
        // 获取手机号
        String curPhone = userDetailDo.getPhoneNumber();
        if (Objects.isNull(curPhone)) throw new BizException(ResponseCodeEnum.USER_UNBIND_PHONE);

        // 对比手机号
        if (!Objects.equals(curPhone, phone)) throw new BizException(ResponseCodeEnum.PHONE_NUMBER_VALIDATE_ERROR);

        // 验证完成，解绑手机号
        userDetailDo.setPhoneNumber(null);
        LambdaUpdateWrapper<UserDetailDo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(UserDetailDo::getPhoneNumber, null);
        updateWrapper.eq(UserDetailDo::getId, userDetailDo.getId());
        userDetailMapper.update(userDetailDo, updateWrapper);
        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageResponse findUserDetailPageList(FindUserDetailPageListReqVo vo) {
        // 将vo转换为qo
        UserDetailQo userDetailQo = UserConvert.INSTANCE.pageVo2Qo(vo);

        // 进行分页查询
        Page<UserDetailDo> page = userDetailMapper.selectUserDetailPageList(userDetailQo);
        // 获取分页数据
        List<UserDetailDo> userDetailDos = page.getRecords();

        // 将数据格式从do转换为vo
        List<FindUserDetailPageListRspVo> vos = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(userDetailDos)) {
            // 遍历分页数据
            userDetailDos.forEach(userDetailDo -> {
                // 将do转换为vo
                FindUserDetailPageListRspVo findUserDetailPageListRspVo = UserConvert.INSTANCE.do2pageVo(userDetailDo);
                // 获取用户id
                Long userId = Long.valueOf(findUserDetailPageListRspVo.getUserId());
                // 查询用户账号信息
                UserDo userDo = userMapper.selectById(userId);
                if (Objects.isNull(userDo)) {
                    log.warn("【用户后台服务】 账户不存在！用户id：{}", userId);
                } else {
                    // 获取账号状态信息
                    UserAccountStatusEnum statusEnum = UserAccountStatusEnum.getEnumByCode(userDo.getStatus());
                    if (Objects.isNull(statusEnum)) {
                        log.warn("【用户后台服务】 账号状态异常！用户id：{}", userId);
                        statusEnum = UserAccountStatusEnum.ACCOUNT_NORMAL;
                    }
                    // 判断是否过期
                    if (!Objects.equals(UserAccountStatusEnum.ACCOUNT_NORMAL.getCode(), statusEnum.getCode())) {
                        // 获取状态有效期
                        LocalDateTime endTime = userDo.getEndTime();
                        log.info(endTime == null ? " null " : endTime.toString() + "   " + LocalDateTime.now());
                        // 转换为时间戳
                        long endTimeStamp = Objects.isNull(endTime) ? 0L : DateUtil.localDateTime2TimeStamp(endTime);
                        // 获取当前时间戳
                        long currentTimeStamp = DateUtil.localDateTime2TimeStamp(LocalDateTime.now());
                        if (currentTimeStamp > endTimeStamp) {
                            // 账号状态为禁用或封禁，且当前时间大于有效期，更新状态为正常
                            UpdateWrapper<UserDo> updateWrapper = new UpdateWrapper<>();
                            updateWrapper.eq("id", userId);
                            updateWrapper.set("status", UserAccountStatusEnum.ACCOUNT_NORMAL.getCode());
                            // 开始时间置空
                            updateWrapper.set("start_time", null);
                            // 结束时间置空
                            updateWrapper.set("end_time", null);
                            // 封禁原因置空
                            updateWrapper.set("reason", null);
                            int count = userMapper.update(null, updateWrapper);

                            // 更新成功，更新信息
                            if (count == 1) {
                                userDo.setStatus(UserAccountStatusEnum.ACCOUNT_NORMAL.getCode());
                                userDo.setStartTime(null);
                                userDo.setEndTime(null);
                                userDo.setReason(null);
                            }
                        }
                        log.info(currentTimeStamp + " " + endTimeStamp);
                    }
                    // 设置账号信息
                    findUserDetailPageListRspVo.setUsername(userDo.getUsername());
                    findUserDetailPageListRspVo.setStatus(userDo.getStatus());
                    findUserDetailPageListRspVo.setReason(userDo.getReason());
                    findUserDetailPageListRspVo.setStartTime(userDo.getStartTime());
                    findUserDetailPageListRspVo.setEndTime(userDo.getEndTime());
                }

                // 将vo添加到列表中
                UserAccountStatusEnum statusEnum = UserAccountStatusEnum.getEnumByCode(findUserDetailPageListRspVo.getStatus());
                if (Objects.nonNull(vo.getStatus()) && Objects.nonNull(statusEnum) && !Objects.equals(vo.getStatus(), statusEnum.getCode())) {
                    // 状态不匹配，跳过
                } else {
                    vos.add(findUserDetailPageListRspVo);
                }

            });
        }

        // 返回响应数据
        return PageResponse.success(page, vos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response updateUserMessage(UpdateUserMessageReqVo vo) {
        // 获取用户id
        Long userId = vo.getUserId();
        // 查询用户资料是否存在
        UserDetailDo curUserDetail = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(curUserDetail)) {
            log.warn("【后台用户管理服务】 用户id为{}的资料不存在，无法进行后续操作！", userId);
            throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);
        }
        // 将vo转换为do
        UserDetailDo userDetailDo = UserConvert.INSTANCE.messageVo2DetailDo(vo);
        // 设置id
        userDetailDo.setId(curUserDetail.getId());
        // 设置资料更新时间
        userDetailDo.setUpdateTime(LocalDateTime.now());
        // 更新资料
        userDetailMapper.updateById(userDetailDo);
        // 发布资料修改事件
        eventPublisher.publishEvent(new UpdatePersonMessageEvent(this, userId));

        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response updateUserAccount(UpdateUserAccountReqVo vo) {
        // 获取用户账号更新信息
        Long userId = vo.getUserId();
        // 查询用户表和资料表
        UserDo userDo = userMapper.selectById(userId);
        if (Objects.isNull(userDo)) {
            log.warn("【用户后台管理服务】 用户id为{}的账户不存在", userId);
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        // 查询用户详细资料
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(userDetailDo)) {
            log.warn("【用户后台管理服务】 用户id为{}的账户资料不存在", userId);
            throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);
        }
        // 获取用户密码
        String password = vo.getPassword();
        // 获取用户名
        String username = userDo.getUsername();
        if (StringUtils.isNotBlank(password)) {
            // 校验密码格式
            Preconditions.checkArgument(ValidateUtil.isPassword(password), "密码格式错误！");
            // 更新用户密码
            String encodePassword = passwordEncoder.encode(password);
            userMapper.updatePasswordByUsername(username, encodePassword);
        }

        // 创建更新条件
        LambdaUpdateWrapper<UserDetailDo> updateWrapper = new LambdaUpdateWrapper<>();

        // 获取手机号
        String phone = vo.getPhoneNumber();
        // 获取qq号
        String qqId = vo.getQqId();
        // 获取邮箱
        String mail = vo.getMail();
        if (isBindAccount(phone, qqId, mail)) {
            log.warn("【用户后台管理服务】 用户id为{}的账户修改的账号信息绑定其他账号！", userId);
            throw new BizException(ResponseCodeEnum.USER_MAIL_OR_PHONE_OR_QQ_ALREADY_REGISTER);
        }
        if (StringUtils.isNotBlank(phone) && !Objects.equals(phone, userDetailDo.getPhoneNumber())) {
            // 校验手机号格式
            Preconditions.checkArgument(ValidateUtil.isPhoneNumber(phone), "手机号格式错误！");
            // 更新用户手机号
            updateWrapper.set(UserDetailDo::getPhoneNumber, phone);
            userDetailDo.setPhoneNumber(phone);
        } else if (StringUtils.isBlank(phone) && StringUtils.isNotBlank(userDetailDo.getPhoneNumber())) {
            // 解绑手机号
            updateWrapper.set(UserDetailDo::getPhoneNumber, null);
            userDetailDo.setPhoneNumber(null);
        }

        if (StringUtils.isNotBlank(qqId) &&!Objects.equals(qqId, userDetailDo.getQqId())) {
            // 校验qq号格式
            Preconditions.checkArgument(ValidateUtil.isQqNumber(qqId), "qq号格式错误！");
            // 更新用户qq号
            updateWrapper.set(UserDetailDo::getQqId, qqId);
            userDetailDo.setQqId(qqId);
        } else if (StringUtils.isBlank(qqId) && StringUtils.isNotBlank(userDetailDo.getQqId())) {
            updateWrapper.set(UserDetailDo::getQqId, null);
            userDetailDo.setQqId(null);
        }

        if (StringUtils.isNotBlank(mail) && !Objects.equals(mail, userDetailDo.getMail())) {
            // 校验邮箱格式
            Preconditions.checkArgument(ValidateUtil.isEmail(mail), "邮箱格式错误！");
            // 更新邮箱信息
            updateWrapper.set(UserDetailDo::getMail, mail);
            userDetailDo.setMail(mail);
        }
        // 设置更新日期
        userDetailDo.setUpdateTime(LocalDateTime.now());
        // 设置更新条件
        updateWrapper.eq(UserDetailDo::getUserId, userId);
        updateWrapper.eq(UserDetailDo::getId, userDetailDo.getId());
        // 保存数据
        userDetailMapper.update(userDetailDo, updateWrapper);
        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response updateUserStatus(UpdateUserStatusReqVo vo) {
        // 获取设置信息
        Long userId = vo.getUserId();
        UserDo userDo = userMapper.selectById(userId);
        if (Objects.isNull(userDo)) {
            log.warn("【用户后台管理服务】 用户id为{}的账户不存在！", userId);
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        // 获取状态
        Integer status = vo.getStatus();
        Integer currStatus = userDo.getStatus();
        if (!Objects.equals(status, UserAccountStatusEnum.ACCOUNT_NORMAL.getCode())) {
            // 用户状态异常，获取异常理由
            String reason = vo.getReason();
            LocalDateTime startTime = vo.getStartTime();
            LocalDateTime endTime = vo.getEndTime();

            if (Objects.isNull(startTime) || Objects.isNull(endTime)) {
                log.warn("【用户后台管理服务】 传入起始时间存在空！");
                throw new BizException(ResponseCodeEnum.START_OR_END_TIME_EXIST_NULL);
            }

            if (Objects.equals(status, UserAccountStatusEnum.ACCOUNT_RESTRICT.getCode())) {
                // 设置禁言状态
                reason = StringUtils.isBlank(reason) ? "用户违反平台规定，但情节较轻，禁言处理！" : reason;
                userDo.setStatus(UserAccountStatusEnum.ACCOUNT_RESTRICT.getCode());
            } else if (Objects.equals(status, UserAccountStatusEnum.ACCOUNT_SUSPENSION.getCode())) {
                // 设置封禁状态
                reason = StringUtils.isBlank(reason) ? "用户严重违反平台规定，做账号封禁处理！" : reason;
                userDo.setStatus(UserAccountStatusEnum.ACCOUNT_SUSPENSION.getCode());
            }
            // 更新数据
            userDo.setReason(reason);
            userDo.setStartTime(startTime);
            userDo.setEndTime(endTime);
            userMapper.updateById(userDo);
        } else if (Objects.equals(status, UserAccountStatusEnum.ACCOUNT_NORMAL.getCode()) && !Objects.equals(status, currStatus)){
            // 修改为正常状态
            LambdaUpdateWrapper<UserDo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(UserDo::getStartTime, null);
            userDo.setStartTime(null);
            updateWrapper.set(UserDo::getEndTime, null);
            userDo.setEndTime(null);
            updateWrapper.set(UserDo::getReason, vo.getReason());
            userDo.setReason(vo.getReason());
            updateWrapper.set(UserDo::getStatus, UserAccountStatusEnum.ACCOUNT_NORMAL.getCode());
            userDo.setStatus(UserAccountStatusEnum.ACCOUNT_NORMAL.getCode());

            updateWrapper.eq(UserDo::getId, userDo.getId());
            // 保存
            userMapper.update(userDo, updateWrapper);
        } else {
            log.warn("【用户后台管理服务】 设置状态非法或状态重复修改为相同值！");
            throw new BizException(ResponseCodeEnum.ACCOUNT_STATUS_NOT_EXIST);
        }

        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response cancelUserAccount(DeleteUserAccountReqVo vo) {
        // 获取需要注销的用户id
        Long userId = vo.getUserId();

        // 查询用户是否存在
        UserDo userDo = userMapper.selectById(userId);
        if (Objects.isNull(userDo)) {
            log.warn("【用户后台管理服务】 用户id为{}的账户不存在！", userId);
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        // 查询用户是否存在资料
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(userDetailDo)) {
            log.warn("【用户后台管理服务】 用户id为{}的账户资料不存在", userId);
            throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);
        }
        // 获取用户名
        String username = userDo.getUsername();
        // 查询用户角色列表
        List<UserRoleDo> userRoleDos = userRoleMapper.selectUserRoleByUsername(username);

        // 将用户账号逻辑删除
        userDo.setIsDeleted(true);
        userMapper.updateById(userDo);
        // 将用户信息逻辑删除
        userDetailDo.setIsDeleted(true);
        userDetailMapper.updateById(userDetailDo);
        // 将用户角色表角色逻辑删除
        if (!CollectionUtils.isEmpty(userRoleDos)) {
            userRoleDos.forEach(userRoleDo -> {
                userRoleDo.setIsDeleted(true);
                userRoleMapper.updateById(userRoleDo);
            });
        }

        return Response.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response recoverUserAccount(RecoverUserAccountReqVo vo) {
        // 获取需要恢复的用户id
        Long userId = vo.getUserId();
        // 查询用户是否存在
        UserDo userDo = userMapper.selectById(userId);
        if (Objects.isNull(userDo)) {
            log.error("【用户后台管理服务】 用户id为{}的账户不存在！", userId);
            throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        }
        // 查询用户是否存在资料
        UserDetailDo userDetailDo = userDetailMapper.selectUserDetailByUserId(userId);
        if (Objects.isNull(userDetailDo)) {
            log.error("【用户后台管理服务】 用户id为{}的账户资料不存在", userId);
            throw new BizException(ResponseCodeEnum.USER_DETAIL_NOT_EXIST);
        }
        // 获取用户名
        String username = userDo.getUsername();
        // 获取用户是否注销
        boolean isDeleted = userDo.getIsDeleted() || userDetailDo.getIsDeleted();
        if (isDeleted) {
            // 用户已注销，恢复用户
            userDo.setIsDeleted(false);
            userMapper.updateById(userDo);
            // 恢复资料
            userDetailDo.setIsDeleted(false);
            userDetailMapper.updateById(userDetailDo);
            // 恢复角色
            List<UserRoleDo> userRoleDos = userRoleMapper.selectUserRoleByUsername(username);
            if (!CollectionUtils.isEmpty(userRoleDos)) {
                userRoleDos.forEach(userRoleDo -> {
                    userRoleDo.setIsDeleted(false);
                    userRoleMapper.updateById(userRoleDo);
                });
            }
        }
        return Response.success();
    }

    // 验证邮箱，手机号，qq号是否被其他账号绑定
    private Boolean isBindAccount(String phone, String mail, String qqId) {
        return userDetailMapper.selectUserByMailOrPhoneOrQQ(mail, phone, qqId) != null;
    }
    // 判断是否为数字
    private Boolean isPureNumber(String str) {
        return str.matches("\\d+");
    }
    // 验证账号信息
    private UserDo validateUserCount(Long userId, String username, String password) {
        // 获取当前登录用户用户名
        String currentLoginUsername = getUserUsername();

        // 对比用户名是否相同
        if (!Objects.equals(currentLoginUsername, username)) {
            // 不相同，表示登录用户与修改用户不一致
            throw new BizException(ResponseCodeEnum.USER_NOT_CONSISTENT);
        }

        // 查询用户账户是否存在
        UserDo userDo = userMapper.findByUsername(username);
        if (Objects.isNull(userDo)) throw new BizException(ResponseCodeEnum.USERNAME_NOT_FOUND);
        // 检查id是否一致
        if (!Objects.equals(userDo.getId(),  userId)) {
            throw new BizException(ResponseCodeEnum.USER_NOT_CONSISTENT);
        }
        // 验证密码是否一致
        if (!passwordEncoder.matches(password, userDo.getPassword())) throw new BizException(ResponseCodeEnum.PASSWORD_VALIDATE_ERROR);

        return userDo;
    }

    // 格式化手机号
    private String formatPhoneNumber(String phoneNumber) {
        if (StringUtils.isBlank(phoneNumber)) return "";
        // 获取手机号长度
        Integer size = phoneNumber.length();
        StringBuilder stringBuilder = new StringBuilder(size);
        // 长度在11位以及以上，保留前两位，后四位
        if (size >= 11) {
            stringBuilder.append(phoneNumber, 0, 2);
            for (int i = 0; i < size - 6; i ++) stringBuilder.append("*");
            stringBuilder.append(phoneNumber, size - 4, size);
        } else if (size >= 5) {
            // 长度在5-10位，保留前一位，后俩位
            stringBuilder.append(phoneNumber, 0, 1);
            for (int i = 0; i < size - 3; i ++) stringBuilder.append("*");
            stringBuilder.append(phoneNumber, size - 2, size);
        } else {
            // 长度小于5位，不保留任何信息
            for (int i = 0; i < size; i ++) stringBuilder.append("*");
        }
        return stringBuilder.toString();
    }

    // 获取登录用户的用户名
    private String getUserUsername() {
        // 获取储存在ThreadLocal中的用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication.getName();
    }
    // 判断用户是否存在
    private Boolean isExistUserCount(Long userId) {
        // 查询用户
        UserDo userDo = userMapper.selectById(userId);
        if (Objects.isNull(userDo)) return false;
        else return true;
    }
    // 默认新增信息
    private void autoGenerateUserDetail(Long userId, String username) {
        // 生成UUID
        String uuidStr = UUID.randomUUID().toString();
        String mail = "请尽快设置邮箱！" + uuidStr;
        // 设置默认头像
        String avatar = defaultImageUrl;
        // 设置签名
        String signature = "该用户很懒，还没有设置个性签名哟！";
        // 查找用户角色表
        List<UserRoleDo> userRoleDos = userRoleMapper.selectUserRoleByUsername(username);
        Boolean isAdmin = false;
        // 遍历用户角色
        if (!CollectionUtils.isEmpty(userRoleDos)) {
            for (UserRoleDo userRoleDo : userRoleDos) {
                if (Objects.equals("ROLE_ADMIN", userRoleDo.getRole())) {
                    isAdmin = true;
                    break;
                }
            }
        }
        // 其他按照数据库默认值
        // 构建do
        UserDetailDo userDetailDo = UserDetailDo.builder()
                .userId(userId)
                .nickname(username)
                .avatar(avatar)
                .mail(mail)
                .signature(signature)
                .isAdmin(isAdmin)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .birthday(LocalDate.now())
                .build();

        // 保存
        userDetailMapper.insert(userDetailDo);
    }
}
